#ifndef __EVENT_H__
#define __EVENT_H__

class EmptyType {};
typedef EmptyType Delegater;

template <typename EventFuncType>
class EventObject
{
public:
	EventObject() : ObjPtr(NULL), FuncPtr(NULL) {}
	template <typename ObjectType, typename MemberFuncType>
	EventObject(ObjectType* pObj, MemberFuncType pMemberFunc)
	{
		ObjPtr = (EmptyType*)pObj;
		FuncPtr = *((EventFuncType*)&pMemberFunc);
	}
public:
	EmptyType* ObjPtr;
	EventFuncType FuncPtr;
};

template <typename EventFuncType>
class Event
{
public:
	friend class Object;
public:
	typedef std::vector<EventObject<EventFuncType>> EventList;
	typedef typename std::vector<EventObject<EventFuncType>>::iterator EventIterator;
public:
	Event() : pEventList(NULL) {}
	virtual ~Event()
	{
		if (pEventList) 
		{
			delete pEventList;
			pEventList = NULL;
		}
	}
	template <typename ObjectType, typename MemberFuncType>
	void Listen(ObjectType* pObj, MemberFuncType pMemberFunc)
	{
		EventObject<EventFuncType> eventObj;
		this->operator += eventObj;
	}

	template <typename ObjectType, typename MemberFuncType>
	void Unlisten(ObjectType* pObj, MemberFuncType pMemberFunc)
	{
		EventObject<EventFuncType> eventObj(pObj, pMemberFunc);
		this->operator -= eventObj;
	}

	void operator +=(EventObject<EventFuncType>& eventObj)
	{
		if (!pEventList) pEventList = new EventList();
		bool bFind = false;
		EventIterator iter;
		for (iter = pEventList->begin(); iter != pEventList->end(); ++iter)
		{
			if (iter->ObjPtr == eventObj.ObjPtr && iter->FuncPtr == eventObj.FuncPtr)
			{
				bFind = true;
				break;
			}
		}
		if (!bFind) pEventList->push_back(eventObj);
	}

	void operator -=(EventObject<EventFuncType>& eventObj)
	{
		if (!pEventList) return;
		EventIterator iter;
		for (iter = pEventList->begin(); iter != pEventList->end(); ++iter)
		{
			if (iter->ObjPtr == eventObj.ObjPtr && iter->FuncPtr == eventObj.FuncPtr)
			{
				pEventList->erase(iter);
				break;
			}
		}
	}
public:
	EventList* pEventList;
};

#define FireEvent(type, event, params)\
{\
	if (event.pEventList && (!event.pEventList->empty()))\
	{\
		for(int i = static_cast<int>(event.pEventList->size()) - 1; i >=0; --i)\
		{\
			EventObject<type>& obj = (*event.pEventList)[i];\
			((obj.ObjPtr)->*(obj.FuncPtr))params;\
		}\
	}\
}

//#define FireEvent(type, event, params)\
//{\
//    if (event.pEventList && (!event.pEventList->empty()))\
//    {\
//        Event<type>::EventIterator iter;\
//        for(iter = event.pEventList->begin(); iter != event.pEventList->end(); ++iter)\
//        {\
//            ((iter->ObjPtr)->*(iter->FuncPtr))params;\
//        }\
//    }\
//}

#endif